home *** CD-ROM | disk | FTP | other *** search
- /*
- * desktop.c - functions related to desktop database
- */
-
- #include "RevRdist.h"
- #include <Finder.h>
- #include "desktop.h"
-
- static Handle APPLh; /* handle to APPL resource */
- static Integer Deskrefnum; /* refnum for desktop file */
- static Integer ClientDTRef; /* refnum for client desktop data base */
- static Integer ServerDTRef; /* refnum for server desktop data base */
-
- /*
- * Structure of application info in Desktop file
- */
- struct applinfo
- {
- OSType creator; /* creator/owner id */
- Longint dirID; /* directory containing appl */
- /* char applname[0]; /* file name */
- };
- typedef struct applinfo api_t;
-
- void modify_dtfile (cnode_t *, Boolean);
-
-
-
- /*
- *=========================================================================
- * desktop_end() - release access to desktop files, etc
- *=========================================================================
- */
- void
- desktop_end(void)
- {
- if (APPLh)
- {
- ReleaseResource(APPLh);
- APPLh = nil;
- }
- if (Deskrefnum)
- CloseResFile (Deskrefnum);
- Deskrefnum = 0;
- ClientDTRef = 0;
- ServerDTRef = 0;
- }
-
-
- /*
- *=========================================================================
- * desktop_remove(cip, cp) - remove info for file from desktop
- * entry: cp = ptr to cnode for file to remove
- * desktop_start() called
- * exit: information about file removed from desktop database
- *=========================================================================
- */
- void
- desktop_remove(cnode_t *cp)
- {
- OSErr error;
- DTPBRec cdtpb; /* client desktop parameter block */
- int didit;
-
- Clue0 = "\pdesktop_remove";
- if (ClientDTRef)
- {
- didit = 0;
- if (Flags & PF_LISTONLY)
- return;
- ZERO(cdtpb);
- cdtpb.ioDTRefNum = ClientDTRef;
- cdtpb.ioNamePtr = cp->name;
- cdtpb.ioDirID = cp->parID;
- error = PBDTRemoveComment(&cdtpb, false);
- if (error && error != afpItemNotFound && error != fnfErr)
- {
- ClueID = error;
- warning (E_SYS, Clue1, "\pPBDTRemoveComment", nil);
- }
- if (error == 0)
- didit = 1;
- if (cp->in.f.finfo.fdType == 'APPL' && (cp->in.f.finfo.fdFlags & fHasBundle))
- {
- cdtpb.ioTagInfo = 0;
- cdtpb.ioFileCreator = cp->in.f.finfo.fdCreator;
- error = PBDTRemoveAPPL(&cdtpb, false);
- if (error && error != afpItemNotFound && error != fnfErr)
- {
- ClueID = error;
- warning (E_SYS, Clue1, "\pPBDTRemoveAPPL", nil);
- }
- if (error == 0)
- didit = 1;
- }
- if (didit && (Flags & PF_VERBOSE))
- notice (L_DTDEL, cp->name, nil);
- return;
- }
- /*
- * Here if old style Desktop file
- */
- modify_dtfile (cp, false);
- }
-
-
-
- /*
- *=========================================================================
- * desktop_start() - get access to desktop files, etc
- * entry: ClientVol, ServerVol set
- * ClientVIB, ServerVIB set
- * returns: OSErr if cannot open database
- *=========================================================================
- */
- OSErr
- desktop_start(void)
- {
- OSErr error;
- Integer cur; /* saved current resource file */
- Handle hdl; /* temp handle to APPL resource */
- DTPBRec dtpb; /* desktop database info */
- HParamBlockRec hpb; /* for GetVInfo, etc calls */
- GetVolParmsInfoBuffer vib; /* for GetVolParms */
- Str255 s; /* string temp */
-
- Clue0 = "\pdesktop_start";
- ClientDTRef = 0;
- ServerDTRef = 0;
- if (ServerVIB.vMAttrib & (1<<bHasDesktopMgr))
- {
- ZERO (dtpb);
- dtpb.ioVRefNum = ServerVol;
- error = PBDTGetPath(&dtpb);
- if (error)
- {
- ClueID = error;
- warning (E_SYS, Clue0, "\pPBDTGetPath", nil);
- } else {
- ServerDTRef = dtpb.ioDTRefNum;
- }
- }
- if (ClientVIB.vMAttrib & (1<<bHasDesktopMgr))
- {
- ZERO (dtpb);
- dtpb.ioVRefNum = ClientVol;
- error = PBDTGetPath(&dtpb);
- if (error)
- {
- ClueID = error;
- warning (E_SYS, Clue0, "\pPBDTGetPath", nil);
- } else {
- ClientDTRef = dtpb.ioDTRefNum;
- }
- }
- if (ClientDTRef == 0)
- {
- /*
- * No Desktop database, use old style Desktop file and get APPL resource
- */
- hdl = GetResource ('APPL', 0); /* see if available already (debugging) */
- if (hdl == 0)
- {
- /*
- * Try to open Finder's Desktop file to find resource
- */
- cur = CurResFile();
- Deskrefnum = OpenRFPerm("\pDesktop", ClientVol, fsRdWrPerm);
- if (Deskrefnum == -1)
- Deskrefnum = 0; /* could not open desktop */
- else
- hdl = GetResource ('APPL', 0);
- UseResFile(cur);
- }
- if (hdl == 0)
- {
- if (Deskrefnum)
- {
- CloseResFile (Deskrefnum);
- Deskrefnum = 0;
- }
- }
- APPLh = hdl;
- }
- return 0;
- }
-
-
-
- /*
- *=========================================================================
- * desktop_update(sp, cp) - add/update info for file in desktop databases
- * entry: sp = ptr to cnode for server file cp is a copy of
- * cp = ptr to cnode for client file
- * desktop_start() called
- * exit: information about file added to or updated in desktop database
- *=========================================================================
- */
- void
- desktop_update (cnode_t *sp, cnode_t *cp)
- {
- OSErr error;
- int i, j; /* temp index */
- int modified; /* non-zero if database updated */
- int once = 0; /* used to issue messages only once */
- int t; /* temp */
- DTPBRec cdtpb; /* client desktop parameter block */
- DTPBRec sdtpb; /* server desktop parameter block */
- char buf[1024]; /* buffer for icons or comments */
- static struct /* icon information */
- {
- int itype;
- int isize;
- } ii[] =
- { {kLargeIcon, kLargeIconSize}
- , {kLarge4BitIcon, kLarge4BitIconSize}
- , {kLarge8BitIcon, kLarge8BitIconSize}
- , {kSmallIcon, kSmallIconSize}
- , {kSmall4BitIcon, kSmall4BitIconSize}
- , {kSmall8BitIcon, kSmall8BitIconSize}
- };
-
- Clue0 = "\pdesktop_update";
- modified = 0;
- /*
- * Always update comment information, when available
- */
- if (ClientDTRef && ServerDTRef)
- {
- ZERO (sdtpb);
- sdtpb.ioNamePtr = sp->name;
- sdtpb.ioDTRefNum = ServerDTRef;
- sdtpb.ioDTBuffer = buf;
- sdtpb.ioDTReqCount = sizeof(buf);
- sdtpb.ioDirID = sp->parID;
- Clue1 = "\pPBDTGetComment";
- error = PBDTGetComment (&sdtpb, false);
- if (error == afpItemNotFound || error == fnfErr || error == afpAccessDenied)
- {
- /*
- * The AccessDenied clause above is for Novell, which requires
- * "Write To File" access to read the comments???
- */
- sdtpb.ioDTActCount = 0;
- error = 0;
- }
- if (error == 0)
- {
- /*
- * If empty comment on server, don't cause write on client unless
- * we have to.
- */
- if (sdtpb.ioDTActCount == 0)
- {
- ZERO (cdtpb);
- cdtpb.ioNamePtr = cp->name;
- cdtpb.ioDTRefNum = ClientDTRef;
- cdtpb.ioDirID = cp->parID;
- cdtpb.ioDTBuffer = buf + sizeof(buf)/2;
- cdtpb.ioDTReqCount = sizeof(buf)/2;
- error = PBDTGetComment (&cdtpb, false);
- if (error == 0 && cdtpb.ioDTActCount == 0)
- {
- error = afpItemNotFound; /* fake error to skip SetComment */
- }
- if (error == afpAccessDenied)
- error = afpItemNotFound; /* also for Novell */
- }
- if (error == 0)
- {
- ZERO (cdtpb);
- cdtpb.ioNamePtr = cp->name;
- cdtpb.ioDTRefNum = ClientDTRef;
- cdtpb.ioDirID = cp->parID;
- cdtpb.ioDTBuffer = buf;
- cdtpb.ioDTReqCount = sdtpb.ioDTActCount;
- if (Flags & PF_VERBOSE)
- notice (L_DTCOMM, cp->name, nil);
- if (!(Flags & PF_LISTONLY))
- {
- error = PBDTSetComment (&cdtpb, false);
- Clue1 = "\pPBDTSetComment";
- if (error == 0)
- modified = 1;
- }
- }
- }
- if (error && error != afpItemNotFound && error != fnfErr)
- {
- ClueID = error;
- warning (E_SYS, Clue0, Clue1, nil);
- }
- }
- /*
- * If the file does not have a bundle, we are done
- */
- if ((sp->in.f.finfo.fdFlags & fHasBundle) == 0)
- goto out;
- /*
- * Copy any icons
- */
- if (ClientDTRef && ServerDTRef)
- {
- for (i = 1, error = 0; ; i++)
- {
- ZERO (sdtpb);
- sdtpb.ioDTRefNum = ServerDTRef;
- sdtpb.ioIndex = i;
- sdtpb.ioFileCreator = sp->in.f.finfo.fdCreator;
- sdtpb.ioIconType = 0;
- error = PBDTGetIconInfo (&sdtpb, false);
- if (error)
- {
- if (error != afpItemNotFound && error != fnfErr)
- {
- ClueID = error;
- warning (E_SYS, Clue0, "\pPBDTGetIconInfo", nil);
- }
- break;
- }
- /*
- * Check for valid icon types
- */
- for (j = 0; t = ii[j].itype; j++)
- if (t == sdtpb.ioIconType)
- break;
- if (t == 0)
- continue; /* ignore if not good icon type */
- sdtpb.ioTagInfo = 0;
- sdtpb.ioDTBuffer = buf;
- sdtpb.ioDTReqCount = ii[j].isize;
- error = PBDTGetIcon (&sdtpb, false);
- if (error)
- {
- ClueID = error;
- warning(E_SYS, Clue0, "\pPBDTGetIcon", nil);
- continue;
- }
- ZERO(cdtpb);
- cdtpb.ioDTRefNum = ClientDTRef;
- cdtpb.ioDTBuffer = buf;
- cdtpb.ioDTReqCount = sdtpb.ioDTActCount;
- cdtpb.ioIconType = sdtpb.ioIconType;
- cdtpb.ioFileCreator = sdtpb.ioFileCreator;
- cdtpb.ioFileType = sdtpb.ioFileType;
- if (once++ == 0 && (Flags & PF_VERBOSE))
- notice (L_DTICON, cp->name, nil);
- if (!(Flags & PF_LISTONLY))
- {
- error = PBDTAddIcon (&cdtpb, false);
- if (error)
- {
- ClueID = error;
- warning(E_SYS, Clue0, "\pPBDTAddIcon", nil);
- }
- else
- modified = 1;
- }
- }
- }
- /*
- * Last, update application location information
- */
- if (cp->in.f.finfo.fdType != 'APPL')
- goto out;
- if (ClientDTRef)
- {
- ZERO(cdtpb);
- cdtpb.ioNamePtr = cp->name;
- cdtpb.ioDTRefNum = ClientDTRef;
- cdtpb.ioDirID = cp->parID;
- cdtpb.ioFileCreator = cp->in.f.finfo.fdCreator;
- if (!(Flags & PF_LISTONLY))
- {
- error = PBDTAddAPPL (&cdtpb, false);
- if (error)
- {
- ClueID = error;
- warning(E_SYS, Clue0, "\pPBDTAddAPPL", nil);
- }
- else
- modified = 1;
- }
- if (modified && (Flags & PF_VERBOSE))
- notice (L_DTINFO, cp->name, nil);
- out:
- if (modified)
- {
- ZERO(cdtpb);
- cdtpb.ioDTRefNum = ClientDTRef;
- error = PBDTFlush(&cdtpb, false);
- if (error)
- {
- ClueID = error;
- warning(E_SYS, Clue0, "\pPBDTFlush", nil);
- }
- }
- return;
- }
- /*
- * We get here if there is no client desktop database and so we
- * need to update the Desktop file ourselves
- */
- modify_dtfile (cp, true);
- }
-
-
-
- /*
- *=========================================================================
- * modify_dtfile (cp, flag) - modify entry in old style Finder Desktop file
- * entry: cp = ptr to cnode of file whose entry is to change
- * flag = true to add/update current information
- * = false to delete current information
- *=========================================================================
- */
- void
- modify_dtfile (cnode_t *cp, Boolean flag)
- {
- OSType creator; /* application signature */
- int doit; /* set if decide need to munge it */
- int exact; /* exact match flag */
- api_t * fp; /* pointer to ap info header */
- Handle hdl = 0; /* handle to APPL resource */
- SignedByte hflags; /* handle state */
- Size len; /* temp byte length */
- Size newlen; /* size of updated entry */
- Size origlen; /* original resource size */
- Size offset; /* offset of signature in APPL rsrc */
- Ptr p, ep;
- StringPtr s; /* temp string ptr */
- struct {
- api_t api;
- Str31 applname;
- } newinfo; /* new application info */
-
- hdl = APPLh;
- if (hdl == NULL)
- return; /* if not available */
- hflags = HGetState(hdl);
- LoadResource (hdl);
- if (ResError())
- return;
- HLock(hdl);
- creator = cp->in.f.finfo.fdCreator;
- doit = 1; /* assume work to do */
- /*
- * Now, search the resource for an entry with a matching creator
- */
- origlen = GetHandleSize (hdl);
- for (p = *hdl, ep = p + origlen; p < ep; p += len)
- {
- fp = (api_t *)p;
- s = (StringPtr) (fp+1);
- len = sizeof(*fp) + (s[0] | 1) + 1;
- if (fp->creator == creator)
- {
- /*
- * Found existing entry.
- * If updating, exit immediately if nothing different.
- * If deleting, delete only on exact match
- */
- exact = fp->dirID == cp->parID
- && EqualString (s, cp->name, false, true);
- if (flag)
- {
- if (exact)
- doit = 0;
- break;
- }
- else
- {
- if (exact)
- break;
- }
- }
- }
- offset = p - *hdl;
- if (offset >= origlen) /* if no entry found */
- {
- len = 0;
- if (!flag) /* if deleting and no entry, done */
- doit = 0;
- }
- if (doit)
- {
- if (flag)
- {
- newinfo.api.creator = creator;
- newinfo.api.dirID = cp->parID;
- COPYPS(cp->name, newinfo.applname);
- newlen = newinfo.applname[0];
- if (newlen & 1)
- newinfo.applname[newlen+1] = 0;
- newlen = sizeof (newinfo.api) + (newlen | 1) + 1;
- }
- else
- newlen = 0;
- /*
- * Use Munger to replace/append/delete new info in resource
- */
- HUnlock(hdl);
- if (Flags & PF_LISTONLY)
- doit = 0;
- if (doit)
- {
- len = Munger(hdl, offset, nil, len, (Ptr)&newinfo, newlen);
- if (len < offset)
- {
- ClueID = len;
- warning (E_SYS, "\pmodify_dtfile", "\pMunger", nil);
- }
- }
- if (doit && (Flags & PF_VERBOSE))
- notice (flag ? L_DTINFO : L_DTDEL, cp->name, nil);
- }
- HSetState (hdl, hflags);
- if (doit)
- {
- ChangedResource (hdl);
- WriteResource (hdl);
- }
- }